package edu.cicese.alz.tests;

import edu.cicese.alz.reports.CustomXYBlockRenderer;
import edu.cicese.alz.util.IncenseUtil;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.DateAxis;
import org.jfree.chart.axis.DateTickMarkPosition;
import org.jfree.chart.axis.SymbolAxis;
import org.jfree.chart.plot.PiePlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.LookupPaintScale;
import org.jfree.chart.renderer.PaintScale;
import org.jfree.chart.title.PaintScaleLegend;
import org.jfree.data.xy.DefaultXYZDataset;
import org.jfree.ui.ApplicationFrame;
import org.jfree.ui.RectangleAnchor;
import org.jfree.ui.RectangleEdge;
import org.jfree.ui.RectangleInsets;

import javax.swing.JPanel;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Paint;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Random;
import java.util.TimeZone;

/**
 * Created by: Eduardo Quintana Contreras
 * Date: 10/07/12
 * Time: 05:56 PM
 */
public class BlockTest2 extends ApplicationFrame {
	DefaultXYZDataset intensityDataset, nfcDataset;

	public BlockTest2(String path) {
		super("Accelerometer Chart");

//		// Create a single plot containing both the scatter and line
//		XYPlot plot = new XYPlot();
//
//		/* SETUP SCATTER */
//		XYSeriesCollection dataset = new XYSeriesCollection();
//		XYSeries data = new XYSeries("data");
//		data.add(3, 2); //Point 1
//		data.add(1, 1); //Point 2
//		data.add(4, 1); //Point 3
//		data.add(2, 2); //Point 4
//		dataset.addSeries(data);
//
//		// Create the scatter data, renderer, and axis
//		XYDataset collection1 = dataset;
//		XYItemRenderer renderer1 = new XYLineAndShapeRenderer(false, true);   // Shapes only
//		ValueAxis domain1 = new NumberAxis("Domain1");
//		ValueAxis range1 = new NumberAxis("Range1");
//
//		// Set the scatter data, renderer, and axis into plot
//		plot.setDataset(0, dataset);
//		plot.setRenderer(0, renderer1);
//		plot.setDomainAxis(0, domain1);
//		plot.setRangeAxis(0, range1);
//
//		// Map the scatter to the first Domain and first Range
//		plot.mapDatasetToDomainAxis(0, 0);
//		plot.mapDatasetToRangeAxis(0, 0);
//
//		/* SETUP LINE */
//
//		XYSeriesCollection dataset2 = new XYSeriesCollection();
//		XYSeries data2 = new XYSeries("data2");
//		data2.add(5, 2); //Point 1
//		data2.add(6, 1); //Point 2
//		data2.add(7, 1); //Point 3
//		data2.add(8, 2); //Point 4
//		dataset2.addSeries(data2);
//		// Create the line data, renderer, and axis
////		XYDataset collection2 = getLinePlotData();
//		XYItemRenderer renderer2 = new XYLineAndShapeRenderer(true, false);   // Lines only
//		ValueAxis domain2 = new NumberAxis("Domain2");
//		ValueAxis range2 = new NumberAxis("Range2");
//
//		// Set the line data, renderer, and axis into plot
//		plot.setDataset(1, dataset2);
//		plot.setRenderer(1, renderer2);
//		plot.setDomainAxis(1, domain2);
//		plot.setRangeAxis(1, range2);
//
//		// Map the line to the second Domain and second Range
//		plot.mapDatasetToDomainAxis(1, 1);
//		plot.mapDatasetToRangeAxis(1, 1);
//
//		// Create the chart with the plot and a legend
//		JFreeChart chart = new JFreeChart("Multi Dataset Chart", JFreeChart.DEFAULT_TITLE_FONT, plot, true);
//		setContentPane(new ChartPanel(chart));

		createDatasetFromCountFiles(path);
		JPanel localJPanel = new ChartPanel(createIntensityChart());
		localJPanel.setPreferredSize(new Dimension(1500, 750));
		setContentPane(localJPanel);
	}

	private JFreeChart createIntensityChart() {
		DateAxis yAxis1 = new DateAxis("Date");
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
		yAxis1.setTickMarkPosition(DateTickMarkPosition.START);
		yAxis1.setDateFormatOverride(sdf);
		yAxis1.setLowerMargin(0.0D);
		yAxis1.setUpperMargin(0.0D);
		yAxis1.setInverted(true);

		DateAxis yAxis2 = new DateAxis("Date");
		yAxis2.setTickMarkPosition(DateTickMarkPosition.START);
		yAxis2.setDateFormatOverride(sdf);
		yAxis2.setLowerMargin(0.0D);
		yAxis2.setUpperMargin(0.0D);
		yAxis2.setInverted(true);

		//		DateAxis yAxis = new DateAxis("Acquisition date");
		//		SimpleDateFormat at = new SimpleDateFormat("yyyy/MM/dd hh:mm");
		//		yAxis.setDateFormatOverride(at);
		//		yAxis.setTickUnit(new DateTickUnit(DateTickUnitType.HOUR,12, at));
		//		yAxis.setTickMarkPosition(DateTickMarkPosition.MIDDLE);
		//		yAxis.setLowerMargin(0.0);
		//		yAxis.setUpperMargin(0.0);

		DateAxis xAxis1 = new DateAxis("Date");
		SimpleDateFormat sdf2 = new SimpleDateFormat("HH:mm");
		xAxis1.setDateFormatOverride(sdf2);
		sdf2.setTimeZone(TimeZone.getTimeZone("GMT"));
		xAxis1.setLowerMargin(0.0D);
		xAxis1.setUpperMargin(0.0D);

		DateAxis xAxis2 = new DateAxis("Date");
		xAxis2.setDateFormatOverride(sdf2);
		xAxis2.setLowerMargin(0.0D);
		xAxis2.setUpperMargin(0.0D);

		CustomXYBlockRenderer renderer1 = new CustomXYBlockRenderer();
		renderer1.setBlockWidth(86400000.0D);
		renderer1.setBlockHeight(60000.0D);
		renderer1.setBlockAnchor(RectangleAnchor.BOTTOM_LEFT);

		CustomXYBlockRenderer renderer2 = new CustomXYBlockRenderer();
		renderer2.setBlockWidth(86400000.0D);
		renderer2.setBlockHeight(60000.0D);
		renderer2.setBlockAnchor(RectangleAnchor.BOTTOM_LEFT);


		XYPlot plot = new XYPlot();

		plot.setDataset(0, intensityDataset);
		plot.setRenderer(0, renderer1);
		plot.setDomainAxis(0, yAxis1);
		plot.setRangeAxis(0, xAxis1);

		plot.setDataset(1, nfcDataset);
		plot.setRenderer(1, renderer2);
		plot.setDomainAxis(1, yAxis2);
		plot.setRangeAxis(1, xAxis2);

		// Map the line to the second Domain and second Range
		plot.mapDatasetToDomainAxis(1, 1);
		plot.mapDatasetToRangeAxis(1, 1);
		// Map the scatter to the first Domain and first Range
		plot.mapDatasetToDomainAxis(0, 0);
		plot.mapDatasetToRangeAxis(0, 0);

//		XYPlot plot = new XYPlot(intensityDataset, yAxis1, xAxis1, renderer1);

		plot.setRangeGridlinesVisible(true);
		plot.setOrientation(PlotOrientation.HORIZONTAL);
//		plot.setBackgroundPaint(Color.WHITE);
//		plot.setRangeGridlinePaint(Color.WHITE);
		plot.setAxisOffset(new RectangleInsets(5.0D, 5.0D, 5.0D, 5.0D));

//		plot.setForegroundAlpha(0.1f);

		JFreeChart chart = new JFreeChart("Multi Dataset Chart", JFreeChart.DEFAULT_TITLE_FONT, plot, true);
		chart.removeLegend();
//		chart.setBackgroundPaint(Color.WHITE);

		LookupPaintScale paintScale = new LookupPaintScale(0.5, 6.5, Color.RED);
		paintScale.add(0.5, new Color(255, 0, 0, 0));
		paintScale.add(1.5, new Color(0, 0, 255, 100));
		paintScale.add(2.5, Color.WHITE);
		paintScale.add(3.5, new Color(220, 243, 148));
		paintScale.add(4.5, new Color(38, 173, 31));
		paintScale.add(5.5, new Color(255, 107, 36));

		renderer1.setPaintScale(paintScale);
//		renderer1.setBlockStroke(null);

		renderer2.setPaintScale(new myPaintScaleClass());
//		renderer2.setBlockStroke(null);

		SymbolAxis localSymbolAxis = new SymbolAxis(null, new String[]{"", "No Data", "No Movement", "Sedentary", "Light", "Moderate", "Hard"});
		localSymbolAxis.setRange(0.5D, 6.5D);
		localSymbolAxis.setPlot(new PiePlot());
		localSymbolAxis.setGridBandsVisible(false);

		PaintScaleLegend localPaintScaleLegend = new PaintScaleLegend(paintScale, localSymbolAxis);
		localPaintScaleLegend.setMargin(new RectangleInsets(3.0D, 10.0D, 3.0D, 10.0D));
		localPaintScaleLegend.setPosition(RectangleEdge.BOTTOM);
		localPaintScaleLegend.setAxisOffset(5.0D);

		chart.addSubtitle(localPaintScaleLegend);

		ChartUtilities.applyCurrentTheme(chart);

		return chart;
	}

	private void createDatasetFromCountFiles(String path) {
		intensityDataset = new DefaultXYZDataset();
		nfcDataset = new DefaultXYZDataset();

		File dir = new File(path);
		FilenameFilter filter = new FilenameFilter() {
			public boolean accept(File dir, String name) {
				return name.toLowerCase().endsWith(".ct");
			}
		};
		File[] files = dir.listFiles(filter);

		if (files != null) {
			double[][] values = new double[3][1440 * files.length];
			double[][] values2 = new double[3][1440 * files.length];
			int day = 0;
			Random random = new Random();

			for (File file : files) {
				try {
					double[][] valuesAux = (double[][]) IncenseUtil.loadData(file.getCanonicalPath());
					for (int i = 0; i < 1440; i++) {
						values[0][day * 1440 + i] = valuesAux[0][i];
						values2[0][day * 1440 + i] = valuesAux[0][i];
						values[1][day * 1440 + i] = i * 60000;
						values2[1][day * 1440 + i] = i * 60000;
						values[2][day * 1440 + i] = getIntensity(valuesAux[2][i]);
						values2[2][day * 1440 + i] = 3.5;
					}
					day++;

				} catch (IOException e) {
					e.printStackTrace();
				}


			}
			intensityDataset.addSeries("Series 1", values);
			nfcDataset.addSeries("Series 2", values2);
		}
	}

	private double getIntensity(double count) {
		if (count == -1) {
			//no data
			return 0.5;
		}
		if (count <= 50) {
			//sedentary
			return 1.5;
		}
		if (count <= 100) {
			//sedentary
			return 2.5;
		}
		if (count <= 1952) {
			//light
			return 3.5;
		}
		if (count <= 5724) {
			//moderate
			return 4.5;
		}
		//hard
		return 5.5;
	}


	public static void main(String[] a) {
		new BlockTest2("D:\\_proyectoAlz\\analysis\\accelerometer\\counts\\0.9\\12").setVisible(true);
	}

	public static class myPaintScaleClass implements PaintScale {

		@Override
		public Paint getPaint(double z) {
			float z01 = (float) z / 198;

			float B = 1;

			float S = (float) Math.max(0.1, Math.abs(2 * z01 - 1));

			float hRed = 0.0f;
			float hBlue = 0.7f;
			float H = hBlue - z01 * (hBlue - hRed);

			// get HSB color, no transparency
			Color c = Color.getHSBColor(H, S, B);

			// adjust transparency here: try 150 instead of 255
			// will lead to same grid effect

			if (c.getRed() == 255 && c.getGreen() == 0 && c.getBlue() == 0) {
				System.out.println("equals");
				return new Color(c.getRed(), c.getGreen(), c.getBlue(), 100);
			}
			else {
				return new Color(c.getRed(), c.getGreen(), c.getBlue(), 255);
			}
		}

		@Override
		public double getUpperBound() {
			return 198;
		}

		@Override
		public double getLowerBound() {
			return 0;
		}
	}
}
